// Channel.cpp
#include "Channel.h"
#include "EventLoop.h"
#include "Logger.h"
#include <cerrno>
#include <sys/epoll.h>
#include <cassert>
#include <unistd.h>
#include <fcntl.h>

namespace GiSo {

// 静态常量初始化
const int Channel::s_NoneEvent = 0;
const int Channel::s_ReadEvent = EPOLLIN | EPOLLPRI; // 可读事件
const int Channel::s_WriteEvent = EPOLLOUT;          // 可写事件

/**
 * @brief Channel 类的构造函数 (私有, 仅 EventLoop 工厂方法可创建).
 *
 * @param loop  Channel 所属的 EventLoop.
 * @param fd    要封装的文件描述符.
 */
Channel::Channel(EventLoop* loop, int fd)
    : m_EventLoop(loop),
      m_Fd(fd),
      m_Event(s_NoneEvent),
      m_Revent(s_NoneEvent),
      m_EventHandling(false) {
        int flags = fcntl(m_Fd, F_GETFL, 0);
        fcntl(m_Fd, F_SETFL, flags | O_NONBLOCK);
    }

/**
 * @brief Channel 类的析构函数.
 *
 * 在析构时，确保 Channel 已从 Poller 中移除，并释放相关资源。
 */
Channel::~Channel() {
    Close();
}

/**
 * @brief 启用读事件监听.
 *
 * 将读事件（EPOLLIN）添加到监听列表中，并通知 Poller 更新监听状态。
 */
void Channel::EnableReading() {
    m_Event |= s_ReadEvent;
    Update();
}

/**
 * @brief 禁用读事件监听.
 *
 * 从监听列表中移除读事件（EPOLLIN），并通知 Poller 更新监听状态。
 */
void Channel::DisableReading() {
    m_Event &= ~s_ReadEvent;
    Update();
}

/**
 * @brief 启用写事件监听.
 *
 * 将写事件（EPOLLOUT）添加到监听列表中，并通知 Poller 更新监听状态。
 */
void Channel::EnableWriting() {
    m_Event |= s_WriteEvent;
    Update();
}

/**
 * @brief 禁用写事件监听.
 *
 * 从监听列表中移除写事件（EPOLLOUT），并通知 Poller 更新监听状态。
 */
void Channel::DisableWriting() {
    m_Event &= ~s_WriteEvent;
    Update();
}

/**
 * @brief 禁用所有事件监听.
 *
 * 移除所有监听事件（包括读、写等），并通知 Poller 更新监听状态。
 */
void Channel::DisableAllEvents() {
    m_Event = s_NoneEvent;
    Update();
}

/**
 * @brief 处理就绪事件 (由 EventLoop::loop() 通过 Poller 调用).
 *
 * 根据 Poller 返回的事件类型，调用相应的回调函数（如读、写、关闭等）。
 */
void Channel::HandleEvent() {

    // 检查是否发生错误事件
    if (m_Revent & EPOLLERR) {
        auto saveErrno = errno;
        if (m_ErrorCallback) {
            m_ErrorCallback();
        }
    }

    // 检查是否发生关闭事件
    if (m_Revent & EPOLLRDHUP) {
        if (m_CloseCallback) {
            m_CloseCallback();
        }
    }

    // 检查是否发生读事件
    if (m_Revent & (EPOLLIN | EPOLLPRI)) {
        if (m_ReadCallback) {
            m_ReadCallback();
        }
    }

    // 检查是否发生写事件
    if (m_Revent & EPOLLOUT) {
        if (m_WriteCallback) {
            m_WriteCallback();
        }
    }

}

/**
 * @brief 更新 Poller 中的 Channel.
 *
 * 通知 Poller 更新当前 Channel 的监听状态（如添加、修改或删除监听事件）。
 */
void Channel::Update() {
    m_EventLoop->UpdateChannel(this);
}

/**
 * @brief 从 Poller 中移除 Channel.
 *
 * 当 Channel 不再需要被监听时，通知 Poller 将其移除。
 */
void Channel::Remove() {
    m_EventLoop->RemoveChannel(this);
}

int Channel::Read(char* buf, size_t len) {
    // 读取数据
    return ::read(m_Fd, buf, len);
}

int Channel::Write(const void* data, size_t len) {
    // 写数据
    ssize_t n = ::write(m_Fd, data, len);
    return n;
}


/**
 * @brief 主动关闭这个channel
 * 
 */
void Channel::Close() {
    // 关闭文件描述符
    if (::close(m_Fd) < 0) {
        // 记录错误日志
        GS_ERROR("Channel::Close - close error: {0}", strerror(errno));
    }
}

/**
 * @brief 处理读事件.
 *
 * 调用预先注册的读事件回调函数。
 */
void Channel::HandleRead() {
    if (m_ReadCallback) {
        m_ReadCallback();
    }
}

/**
 * @brief 处理写事件.
 *
 * 调用预先注册的写事件回调函数。
 */
void Channel::HandleWrite() {
    if (m_WriteCallback) {
        m_WriteCallback();
    }
}

/**
 * @brief 处理关闭事件.
 *
 * 调用预先注册的关闭事件回调函数。
 */
void Channel::HandleClose() {
    if (m_CloseCallback) {
        m_CloseCallback();
    }
}

/**
 * @brief 处理错误事件.
 *
 * 调用预先注册的错误事件回调函数。
 */
void Channel::HandleError() {
    if (m_ErrorCallback) {
        m_ErrorCallback();
    }
}

} // namespace GiSo